package com.deer.wms.inventory.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.inventory.dao.InventoryMapper;
import com.deer.wms.inventory.dao.InventoryTransactMapper;
import com.deer.wms.inventory.model.Inventory.*;
import com.deer.wms.inventory.model.stockTake.StockTakeMaster;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.inventory.util.ExportExcelUtils;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.review.manage.service.BillRecordService;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by 郭靖勋 on 2019/12/18.
 */
@Service
@Transactional
public class InventoryServiceImpl extends SuperServiceImpl<InventoryMapper, Inventory> implements InventoryService {

    @Autowired
    private InventoryMapper inventoryMapper;

    @Autowired
    private InventoryTransactService inventoryTransactService;


    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private BillRecordService billRecordService;

    @Resource
    private ItemInfoService itemInfoService;

    @Override
    public List<Inventory> selectItemByCodes(String cellCode, String boxCode) {
        if (boxCode == null || "".equals(boxCode)) {
            throw new ServiceException(CommonCode.PARAMETER_ERROR, "容器编码不能为空！");
        }
        List<Inventory> inventories = inventoryMapper.selectItemInfo(cellCode, boxCode);
//        if (resultList.size() < 1) {
//            //表示数据库中没有此物料，做盘盈处理，查询物料名称，设置库存为0
//            String itemCode = String.valueOf(resultList.get(0).get("itemCode"));
//            String batchName = String.valueOf(resultList.get(0).get("batchName"));
//            ItemInfo item = itemInfoService.findBy("itemCode", itemCode);
//            if (item == null) {
//                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "没有查询到此物料信息，请检查物料编码是都否正确！");
//            } else {
//                itemMap.put("batchName", batchName);
//                itemMap.put("itemCode", itemCode);
//                itemMap.put("itemName", item.getItemName());
//                itemMap.put("qty", 0);
//            }
////            return itemMap;
//        }
//        else {
//            String batchName1 = String.valueOf(resultList.get(0).get("batchName"));
//            if (batchName1 == null || "".equals(batchName1)) {
//                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "批次件请先扫描批次编码！");
//            } else {
//                Double qty = 0.0;
//                for (Map<String, Object> map : resultList) {
//                    qty += Double.parseDouble(String.valueOf(map.get("qty")));
//                }
//                itemMap = resultList.get(0);
//                itemMap.put("qty", qty);
//            }
//        }
        if (inventories.size() >0){
//            String itemCode = String.valueOf(resultList.get(0).get("itemCode"));
//            String batchName = String.valueOf(resultList.get(0).get("batchName"));
//            String itemName = String.valueOf(resultList.get(0).get("itemName"));
//            String qty = String.valueOf(resultList.get(0).get("qty"));
//            itemMap.put("batchName", batchName);
//            itemMap.put("itemCode", itemCode);
//            itemMap.put("itemName", itemName);
//            itemMap.put("qty", qty);
//            return itemMap;
            return  inventories;
        }else {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "没有查询到该容器下物料信息！");
        }

    }

    //    盘盈入库出库修改库存

    /**
     *
     * @param wareId     仓库id
     * @param itemCode   物料编码
     * @param qty         数量
     * @param inOrOut     入还是出
     */
    @Override
    public void updateInOrOut(Integer wareId, String itemCode, Double qty, String inOrOut) {
        QueryWrapper<Inventory> qw = Wrappers.query();
        Map<String, Object> map = new HashMap<>();
        map.put("ware_id", wareId);
        map.put("item_code", itemCode);
        List<Inventory> inventories = inventoryService.list(qw.allEq(map, false));
        if (inventories.size()>0){//找到一条数据，进行库存修改
            for (Inventory inventory : inventories) {
                Double q = 0.0;
                if ("in".equals(inOrOut)){//表示入库
                    q = inventory.getQuantity() + qty;
                }else {
                    q = inventory.getQuantity() - qty;
                }
                inventory.setQuantity(q);
//                inventory.setInventoryId(invList.get(0).getInventoryId());
                updateById(inventory);
            }

        }
        //根据当前物料编码查询现有的库存
//        List<Inventory> invList = inventoryMapper.findByItemCode(wareId,itemCode);
//        if (invList.size()==0 && "in".equals(inOrOut)){//没有找到数据，表示库存为0
//            //根据物料编码查询物料信息，找到该物料存入库存
//            List<ItemInfo> itemInfos = itemInfoService.findByCode(itemCode);
//            String itemName = itemInfos.get(0).getItemName();
//            Inventory inventory = new Inventory();
//            inventory.setWareId(wareId);
//            inventory.setItemCode(itemCode);
//            inventory.setItemName(itemName);
//            inventory.setQuantity(qty);
//            save(inventory);
//        }
//        else if (invList.size()>0){//找到一条数据，进行库存修改
//            for (Inventory inventory : invList) {
//                Double q = 0.0;
//                if ("in".equals(inOrOut)){//表示入库
//                    q = invList.get(0).getQuantity() + qty;
//                }else {
//                    q = invList.get(0).getQuantity() - qty;
//                }
//                inventory.setQuantity(q);
////                inventory.setInventoryId(invList.get(0).getInventoryId());
//                updateById(inventory);
//            }
//
//        }
//        else if (invList.size()==1){//找到一条数据，进行库存修改
//            Inventory ivt = new Inventory();
//            Double q = 0.0;
//            if ("in".equals(inOrOut)){//表示入库
//                q = invList.get(0).getQuantity() + qty;
//            }else {
//                q = invList.get(0).getQuantity() - qty;
//            }
//            ivt.setQuantity(q);
//            ivt.setInventoryId(invList.get(0).getInventoryId());
//            updateById(ivt);
//        }
        else {
            throw new ServiceException(CommonCode.BATCH_TACTIC_ERROR, "库存表中物料编码重复");
        }
    }


    @Override
    public List<InventoryDto> findList(InventoryCriteria criteria){
        return inventoryMapper.findList(criteria);
    }

    @Override
    public List<InventoryEarlyDto> inventoryEarlyList(InventoryEarlyCriteria criteria){
        return inventoryMapper.inventoryEarlyList(criteria);
    }

//    @Override
//    public List<InventoryEarlyDto> insertEarlyState(List<InventoryEarlyDto> list){
//         for(InventoryEarlyDto dto: list){
//             //历史数据无收货时间
//             if(ObjectUtil.isNotEmpty(dto.getShortEarlyDay())){
//                 //预警天数大于剩余天数,大于0天  临近有效期
//                 if(dto.getEarlyDay()>= dto.getShortEarlyDay() && dto.getShortEarlyDay() >=0){
//                     dto.setEarlyState("1");
//                 }else if(dto.getShortEarlyDay()<0){
//                     dto.setEarlyState("2");
//                 }else{
//                     dto.setEarlyState("0");
//                 }
//             }else{
//                 dto.setEarlyState("");
//             }
//
//         }
//        return list;
//    }
    @Override
    public void exportExcel(HttpServletResponse response, Integer organizationId, String itemCode, String itemName, String cellCode, String batchName,String boxCode,String startTime,String endTime,Integer earlyState) throws Exception {
        ExcelData data = new ExcelData();
        data.setName("有效期预警记录");//sheet表名称
        //表头
        List<String> titles = new ArrayList();
        titles.add("序号");
        titles.add("超期状态");
        titles.add("物料名称");
        titles.add("物料编码");
        titles.add("货位");
        titles.add("批次号");
        titles.add("追踪号");
        titles.add("数量");
        titles.add("有效期(天)");
        titles.add("预警天数(天)");
        titles.add("距离超期天数(天)");
        data.setTitles(titles);
        List<List<Object>> rows = new ArrayList();
        //添加查询条件
        InventoryEarlyCriteria criteria = new InventoryEarlyCriteria();
        criteria.setItemCode(itemCode);
        criteria.setItemName(itemName);
        criteria.setOrganizationId(organizationId);
        criteria.setCellCode(cellCode);
        criteria.setBatchName(batchName);
        criteria.setStartTime(startTime);
        criteria.setEndTime(endTime);
        criteria.setEarlyState(ObjectUtils.isEmpty(earlyState)?null:earlyState);
        criteria.setBoxCode(boxCode);
        criteria.setPageNum(1);
        criteria.setPageSize(999999);
        //调用查询方法
        List<InventoryEarlyDto> returnList = inventoryEarlyList(criteria);
        //封装数据
        rows = getRow(returnList);
        data.setRows(rows);
        ExportExcelUtils.exportExcel(response,"库存记录.xlsx",data);
    }

    private List<List<Object>> getRow(List<InventoryEarlyDto> returnList){
        List<List<Object>> rows = new ArrayList();
        if (returnList.size()>0){
            for (int i=0;i<returnList.size();i++){
                List<Object> row = new ArrayList();
                row.add(i+1);
                if(returnList.get(i).getEarlyState().equals(2)){
                    row.add("超期");
                }else if(returnList.get(i).getEarlyState().equals(1)){
                    row.add("临近有效期");
                }else{
                    row.add("正常");
                }
                row.add(returnList.get(i).getItemName());
                row.add(returnList.get(i).getItemCode());
                row.add(returnList.get(i).getCellCode());
                row.add(returnList.get(i).getBatchName());
                row.add(returnList.get(i).getBoxCode());
                row.add(returnList.get(i).getQuantity());
                row.add(returnList.get(i).getInDate());
                row.add(returnList.get(i).getEarlyDay());
                row.add(returnList.get(i).getShortEarlyDay());
                rows.add(row);
            }
        }
        return rows;
    }

    @Override
    public Inventory  getSameInventory(Integer wareId, String cellCode, String boxCode, Integer packDetailId, String itemCode, Integer batchId, Double transRatio){

        InventoryCriteria inventoryCriteria = new InventoryCriteria();
        inventoryCriteria.setWareId(wareId);
        inventoryCriteria.setCellCode(cellCode);
        inventoryCriteria.setBoxCode(boxCode);
        //inventoryCriteria.setPackDetailId(packDetailId);
        inventoryCriteria.setItemCode(itemCode);
        inventoryCriteria.setBatchId(batchId);
        inventoryCriteria.setTransRatio(transRatio);
        inventoryCriteria.setPageNum(null);
        inventoryCriteria.setPageSize(null);
        Inventory inventory = inventoryMapper.findSameInventory(inventoryCriteria);
        return inventory;
    }

    @Override
    public Inventory  getSameInventoryNew(Integer wareId, String cellCode, String boxCode, Integer packDetailId, String itemCode, String batchName, Double transRatio){

        InventoryCriteria inventoryCriteria = new InventoryCriteria();
        inventoryCriteria.setWareId(wareId);
        inventoryCriteria.setCellCode(cellCode);
        inventoryCriteria.setBoxCode(boxCode);
        inventoryCriteria.setPackDetailId(packDetailId);
        inventoryCriteria.setItemCode(itemCode);
        inventoryCriteria.setBatchName(batchName);
        inventoryCriteria.setTransRatio(transRatio);
        inventoryCriteria.setPageNum(null);
        inventoryCriteria.setPageSize(null);
        Inventory inventory = inventoryMapper.findSameInventory(inventoryCriteria);
        return inventory;
    }

    @Override
    public Inventory getAccept(Integer inventoryId, Integer wareId){
        Inventory inventory = inventoryMapper.getAccept(inventoryId,wareId);
        return inventory;
    }

    @Override
    public Inventory findBatchId(Integer batchId){
        return inventoryMapper.findBatchId(batchId);
    }

    @Override
    public List<InventoryDto> findByCellUseType(InventoryCriteria criteria) {
        return inventoryMapper.findByCellUseType(criteria);
    }

    @Override
    public List<InventorySelectDto> findByInventoryId(InventoryCriteria criteria){
        return inventoryMapper.findByInventoryId(criteria);
    }

    @Override
    public List<InventorySelectDto> findCanBeOutOfStock(InventoryCriteria criteria){
        List<InventorySelectDto> canBeOutOfStocks = inventoryMapper.findCanBeOutOfStock(criteria);
        List<InventorySelectDto> collect = canBeOutOfStocks.stream().filter(stock -> !"zp-SG01".equals(stock.getCellCode())
                && !"zp-NG01".equals(stock.getCellCode())
                && !"zp-GL01".equals(stock.getCellCode()))
                .collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<InventoryToOutDto> findToOutStock(InventoryCriteria criteria) {
        return inventoryMapper.findToOutStock(criteria);
    }

    @Override
    public List<InventoryToUpperDto> findToUpperStock(InventoryCriteria criteria) {
        return inventoryMapper.findToUpperStock(criteria);
    }

    @Override
    public List<InventoryDto> canOut(InventoryCriteria criteria){
        return inventoryMapper.canOut(criteria);
    }

    @Override
    public List<Inventory> findSame(InventoryCriteria criteria) {
        List<Inventory> list = inventoryMapper.findSame(criteria);
        return list;
    }

    @Override
    public List<Inventory> findByCellCode(InventoryCriteria criteria){
        return inventoryMapper.findByCellCode(criteria);
    }

    @Override
    public List<Inventory> findByCellCodeAndState(InventoryCriteria criteria){
        return inventoryMapper.findByCellCode(criteria);
    }

    @Override
    public List<Inventory> checkList(InventoryCriteria criteria) {
        return inventoryMapper.checkList(criteria);
    }

    @Override
    public List<Inventory> findBatchInventory(InventoryCriteria criteria) {
        return inventoryMapper.findBatchInventory(criteria);
    }


    @Override
    public List inventorySafetyList(InventoryCriteria criteria) {
        return inventoryMapper.inventorySafetyList(criteria);
    }

    @Override
    public List<Inventory> palletsToCombine(InventoryCriteria criteria) {
        return inventoryMapper.palletsToCombine(criteria);
    }

    @Override
    public List<Inventory> inventoriesWithBoxCode(String boxCode) {
        return inventoryMapper.inventoriesWithBoxCode(boxCode);
    }

    @Override
    public List<InventoryDto> inventoriesForOut(String boxCode) {
        List<InventoryDto> inventoryDtos = new ArrayList<>();
        QueryWrapper<InventoryTransact> qw = new QueryWrapper<>();
        List<InventoryTransact> list = inventoryTransactService.list(
                qw.eq("from_box_code", boxCode).in("transact_type", 6, 14));

        if (list.isEmpty()) {
            return inventoryDtos;
        }

        for (InventoryTransact inventoryTransact : list) {
            InventoryDto dto = new InventoryDto();
            dto.setItemCode(inventoryTransact.getItemCode());
            dto.setItemName(inventoryTransact.getItemName());
            dto.setBatchName(inventoryTransact.getFromBatchName());
            dto.setBoxCode(inventoryTransact.getFromBoxCode());
            dto.setQuantity(inventoryTransact.getFromQuantity());
            inventoryDtos.add(dto);
        }

        return inventoryDtos;
    }

    @Override
    public List<GroupByWareOrgItem> findGroupByWareOrgItem(InventoryCriteria criteria) {
        return inventoryMapper.findGroupByWareOrgItem(criteria);
    }

    //不考虑批次，单位，跟踪号等等
    @Override
    public String findSameItemCell(String itemCode,Integer wareId,Integer orgId) {
        return inventoryMapper.findSameItemCell(itemCode,wareId,orgId);
    }

    @Override
    public void sendOut(String billNo, Integer wareId) {
        inventoryMapper.sendOut(billNo, wareId);
    }

    @Override
    public List<Inventory> getInventoryByFromInfo(StockTakeMaster stockTakeMaster) {
        return inventoryMapper.getInventoryByFromInfo(stockTakeMaster);
    }

    @Override
    public Inventory findBy(String field, Integer value) {
        QueryWrapper<Inventory> qw = new QueryWrapper<>();
        return getOne(qw.eq(field, value));
    }

    @Override
    public List<Inventory> findListByField(String field, String value) {
        QueryWrapper<Inventory> qw = new QueryWrapper<>();
        return list(qw.eq(field, value));
    }

    @Override
    public Integer getBoxNumInCell(String cellCode) {
        return inventoryMapper.getBoxNumInCell(cellCode);
    }

    @Override
    public Double findAllStock(Integer wareId) {
        return inventoryMapper.findAllStock(wareId);
    }

    @Override
    public Integer findAllSKUs(Integer wareId) {
        return inventoryMapper.findAllSKUs(wareId);
    }

    @Override
    public double findAllStockCells(Integer wareId) {
        return inventoryMapper.findAllStockCells(wareId);
    }

    @Override
    public List<Inventory> getTopSku(Integer wareId, int topNum) {
        return inventoryMapper.getTopSku(wareId, topNum);
    }
}
